package xstr

import (
	"encoding/json"
	"errors"
	"regexp"
	"strconv"
	"strings"

	"github.com/gogf/gf/v2/util/gconv"
	uuid "github.com/satori/go.uuid"
)

// IsBlank ... 是空
func IsBlank(str string) bool {
	return len(strings.TrimSpace(str)) == 0
}

// IsNotBlank ... 非空
func IsNotBlank(str string) bool {
	return !IsBlank(str)
}

// Reverse ... 反序字符串
func Reverse(s string) (result string) {
	for _, v := range s {
		result = string(v) + result
	}
	return
}

// GetKeyStr ... 获得键字符串 注意，key只支持string和int类型！！！
func GetKeyStr(key any) (*string, error) {
	var keyStr string

	switch key.(type) {
	case int, int8, int16, int32, int64:
		if iKey, ok := key.(int64); ok {
			keyStr = strconv.FormatInt(iKey, 10)
		}
	case float32, float64:
		if fKey, ok := key.(float64); ok {
			keyStr = strconv.Itoa(int(fKey))
		}
	case string:
		if sKey, ok := key.(string); ok {
			keyStr = sKey
		}
	case json.Number:
		if iKey, err := key.(json.Number).Int64(); err == nil {
			keyStr = gconv.String(iKey)
		}
	}

	if IsBlank(keyStr) {
		return nil, errors.New("key不能为空！")
	}

	return &keyStr, nil
}

// Contains ... 包含
func Contains(sl []string, str string) bool {
	for _, val := range sl {
		if val == str {
			return true
		}
	}

	return false
}

// GetUUID ... 获得UUID
func GetUUID() string {
	u2 := uuid.NewV4()
	return u2.String()
}

// IsValidUUID 是否是uuid
func IsValidUUID(str string) bool {
	_, err := uuid.FromString(str)
	return err == nil
}

// IsValidPassword 是否有效密码
// 有效密码条件：至少一位大写字母、一位小写字母、一位数字、一个特殊字符(@和_)、8-30位
func IsValidPassword(password string) bool {
	length := len(password)
	if length < 8 || length > 30 {
		return false
	}

	hasUpperLetter := regexp.MustCompile(`[A-Z]`).MatchString
	hasLowerLetter := regexp.MustCompile(`[a-z]`).MatchString
	hasNumber := regexp.MustCompile(`[0-9]`).MatchString
	hasSpecial := regexp.MustCompile("[@_]").MatchString

	return hasUpperLetter(password) && hasLowerLetter(password) && hasNumber(password) && hasSpecial(password)
}

// PadLeft 在原字符串左侧填充指定字符直到满足指定长度
func PadLeft(s string, totalWidth int, padChar rune) string {
	return PadLeftOrRight(s, totalWidth, padChar, true)
}

// PadRight 在原字符串右侧填充指定字符直到满足指定长度
func PadRight(s string, totalWidth int, padChar rune) string {
	return PadLeftOrRight(s, totalWidth, padChar, false)
}

// PadLeftOrRight 在原字符串左侧或右侧填充指定字符直到满足指定长度
func PadLeftOrRight(s string, totalWidth int, padChar rune, isLeft bool) string {
	if len(s) >= totalWidth {
		return s
	}
	pad := strings.Repeat(string(padChar), totalWidth-len(s))

	if isLeft {
		return pad + s
	} else {
		return s + pad
	}
}
